﻿namespace Leetcode.N0420;

public class Solution
{
    public int StrongPasswordChecker(string password)
    {
        var sLength = this.CheckLength(password);
        System.Collections.Generic.List<int> list;
        var sChar = this.CheckChar(password, out list);

        if (sLength >= 0)
        {
            var sRepeat = 0;
            for (int i = 0; i < list.Count; i++)
            {
                sRepeat += list[i] / 3;
            }
            return Math.Max(Math.Max(sLength, sChar), sRepeat);
        }
        else
        {
            var dLength = sLength;
            var hasList = true;

            for (int i = 0; i < list.Count; i++)
            {
                if (list[i] % 3 == 0)
                {
                    dLength++;
                    list[i]--;
                }
                if (list[i] >= 3)
                {
                    hasList = true;
                }
                if (dLength == 0)
                {
                    break;
                }
            }

            if (dLength < 0)
            {
                for (int i = 0; i < list.Count; i++)
                {
                    if (list[i] < 3)
                    {
                        continue;
                    }

                    if (list[i] % 3 == 1)
                    {
                        if (dLength == -1)
                        {
                            dLength++;
                            list[i]--;
                        }
                        else
                        {
                            dLength += 2;
                            list[i] -= 2;
                        }
                    }

                    if (list[i] >= 3)
                    {
                        hasList = true;
                    }

                    if (dLength == 0)
                    {
                        break;
                    }
                }
            }


            while (dLength < 0 && hasList)
            {
                hasList = false;
                for (int i = 0; i < list.Count; i++)
                {
                    if (list[i] < 3)
                    {
                        continue;
                    }

                    if (dLength == -1)
                    {
                        dLength++;
                        list[i]--;
                    }
                    else if (dLength == -2)
                    {
                        dLength += 2;
                        list[i] -= 2;
                    }
                    else
                    {
                        dLength += 3;
                        list[i] -= 3;
                    }
                    if (list[i] >= 3)
                    {
                        hasList = true;
                    }
                    if (dLength == 0)
                    {
                        break;
                    }
                }

            }

            if (dLength < 0)
            {
                return sChar + (-sLength);
            }
            else
            {
                var sRepeat = 0;
                for (int i = 0; i < list.Count; i++)
                {
                    sRepeat += list[i] / 3;
                }
                return Math.Max(sChar, sRepeat) + (-sLength);
            }
        }
    }

    private int CheckLength(string password)
    {
        if (password.Length < 6)
        {
            return 6 - password.Length;
        }
        else if (password.Length > 20)
        {
            return 20 - password.Length;

        }
        return 0;
    }


    private int CheckChar(string password, out System.Collections.Generic.List<int> list)
    {
        var hasUpperChar = false;
        var hasLowerChar = false;
        var hasDight = false;
        var stepCount = 0;

        var repeatCount = 1;
        list = new System.Collections.Generic.List<int>();
        for (int i = 0; i < password.Length; i++)
        {
            if (i > 0)
            {
                if (password[i] == password[i - 1])
                {
                    repeatCount++;
                }
                else
                {
                    if (repeatCount >= 3)
                    {
                        list.Add(repeatCount);
                    }
                    repeatCount = 1;
                }
            }
            if (password[i] >= 'A' && password[i] <= 'Z')
            {
                hasUpperChar = true;
                continue;
            }

            if (password[i] >= 'a' && password[i] <= 'z')
            {
                hasLowerChar = true;
                continue;
            }

            if (password[i] >= '0' && password[i] <= '9')
            {
                hasDight = true;
                continue;
            }
        }

        if (repeatCount >= 3)
        {
            list.Add(repeatCount);
        }

        if (!hasUpperChar)
        {
            stepCount++;
        }

        if (!hasLowerChar)
        {
            stepCount++;
        }

        if (!hasDight)
        {
            stepCount++;
        }
        return stepCount;
    }

    private int GetRepeatCount(string value, int index)
    {
        if (index > 0)
        {
            if (value[index] == value[index - 1])
            {
                return 0;
            }
        }

        var repeatCount = 1;
        for (int i = index + 1; i < value.Length; i++)
        {
            if (value[i] == value[index])
            {
                repeatCount++;
            }
        }
        return repeatCount;
    }
}
